/** @jsxImportSource @emotion/react */
import * as React from "react";
import PropTypes from "prop-types";
import  { forwardRef, useRef, useState } from "react";
import {
    autoUpdate,
    size,
    useId,
    useDismiss,
    useFloating,
    useInteractions,
    useListNavigation,
    useRole,
    FloatingFocusManager,
    FloatingPortal
} from "@floating-ui/react";
import {InputGroupContext, InputSize, useActiveStyle, useSharedStyle} from "./Form";
import {SerializedStyles} from "@emotion/react";


/*参考 原装例子  https://codesandbox.io/s/fragrant-water-bsuirj?file=/src/App.tsx
* */
interface ItemProps {
    children: React.ReactNode;
    active: boolean;
    //手机需要 区分哪一个选项
    index: number;
}

//已经不需要forwardRef<>(()=>{return})这一层皮了；
const Item =({ children, active,index,ref, ...rest }:ItemProps & React.HTMLProps<HTMLDivElement>) => {
    const id = useId();
    return (
        <div
            ref={ref}
            role="option"
            id={id}
            aria-selected={active}
            {...rest}
            style={{
                background: active ? "lightblue" : index%2===0? "none" : "lavender",
                padding: 4,
                cursor: "default",
                ...rest.style
            }}
        >
            {children}
        </div>
    );
};


export interface BlobInputListProps
    extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {
    /** The size of the textarea element */
    inputSize?: InputSize;
    value?: string;
    //topDivStyle?: SerializedStyles;
    //已经知道的列表
    datalist?: any[];
    //还是不该直接走 onChange 参数来做更新回调的；对象类型不一样 Event? : string?;
    //底层input的onChange,参数类型是event:不能直接利用
    onListChange: (value: string|undefined) => void;
    //对弹出列表框的控制  例子：lineStyle={css`max-width:unset;`} , 而不是类似于用css={{}} ；类型不一样的=后者是CSSProperties类型;
    listStyle?: SerializedStyles;
}

/**解决<input>的局限性；
 * TextArea为基础的附加datalist; 因为input只能单一行的无法适应小屏幕大文本的输入； 由于<input 若用大size参数会有屏幕适应性问题！不建议用size设置尺寸！
 * onChange的差别！ props透传赋值的 前面的{...other} 被后面的同名字onChange所覆盖掉！！
 */

export const BlobInputList  = (
    {
        inputSize = "md",
        value,
        style,
        datalist=[],
        placeholder,
        onListChange,
        listStyle,
        ...other
    }:BlobInputListProps) => {
    const { bind, active } = useActiveStyle();
    const {
        baseStyles,
        inputSizes,
        activeBackground,
        errorStyles
    } = useSharedStyle();
    const { uid, error } = React.useContext(InputGroupContext);
    //下面才是列表赋能部分：
    const [open, setOpen] = useState(false);
    const [inputValue, setInputValue] = useState(value);
    const [activeIndex, setActiveIndex] = useState<number | null>(null);
    React.useEffect(() => {
        setInputValue(value);           //被外部修改的 可以同步更新吗？ [侦听]外部协作的输入变动！
    }, [value]);
    const listRef = useRef<Array<HTMLElement | null>>([]);

    const { x, y, refs, strategy, context } = useFloating<
        HTMLInputElement
    >({
        whileElementsMounted: autoUpdate,
        open,
        onOpenChange: setOpen,
        middleware: [
            size({
                apply({ rects, availableHeight, elements }) {
                    Object.assign(elements.floating.style, {
                        width: `${rects.reference.width}px`,
                        maxHeight: `${availableHeight}px`
                    });
                },
                padding: 10
            })
        ]
    });

    // useLayoutEffect(() => {
    //     // IMPORTANT: When the floating element first opens, this effect runs when
    //     // the styles have **not yet** been applied to the element. A rAF ensures
    //     // we wait until the position is ready, and also runs before paint.
    //     // https://floating-ui.com/docs/react-dom#effects
    //     requestAnimationFrame(() => {
    //         if (activeIndex != null) {
    //             listRef.current[activeIndex]?.scrollIntoView({ block: "nearest" });
    //         }
    //     });
    // }, [activeIndex]);

    const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(
        [
            useRole(context, { role: "listbox" }),
            useDismiss(context),
            useListNavigation(context, {
                listRef,
                activeIndex,
                onNavigate: setActiveIndex,
                virtual: true,
                loop: true
            })
        ]
    );

    function onChange(event: React.ChangeEvent<HTMLInputElement>) {
        const value = event.target.value;
        // console.log("商城组件 onChange的： value=",value);
        setInputValue(value);

        if (value) {
            setOpen(true);
            setActiveIndex(0);
        } else {
            setOpen(false);

        }
        onListChange(value);
    }

    const items =inputValue? datalist.filter((item) =>
            item.toLowerCase().includes(inputValue.toLowerCase())
        )
        :
        datalist;       //全部可看
    return (
        <>
            <textarea
                className="BlobInputList"
                id={uid}
                {...bind}
                css={[
                    baseStyles,
                    inputSizes[inputSize],
                    {
                        overflow: "auto",
                        resize:  "vertical",
                    },
                    active && activeBackground,
                    error && errorStyles,
                    {...style}
                ]}

                {...other}

                {...getReferenceProps({
                    ref: refs.setReference,
                    onChange,
                    value: inputValue,
                    placeholder: placeholder,
                    "aria-autocomplete": "list",
                    onKeyDown(event) {
                        if (event.key === "Enter" &&
                            activeIndex != null &&
                            items[activeIndex]) {
                            setInputValue(items[activeIndex]);
                            setActiveIndex(null);
                            setOpen(false);
                        }
                    },
                    onPointerDown(event) {
                        setOpen(true);
                    },
                    style: {
                        ...style,
                    }
                })}


            />

            <FloatingPortal>
                {open && (
                    <FloatingFocusManager
                        context={context}
                        initialFocus={-1}
                        visuallyHiddenDismiss
                    >
                        <div
                            {...getFloatingProps({
                                ref: refs.setFloating,
                                style: {
                                    position: strategy,
                                    left: x ?? 0,
                                    top: y ?? 0,
                                    background: "#eee",
                                    color: "black",
                                    overflowY: "auto",
                                }
                            })}
                            css={{
                                ...listStyle
                            }}
                        >
                            {items.map((item, index) => (
                                <Item  index={index}
                                    {...getItemProps({
                                        key: item,
                                        ref(node) {
                                            listRef.current[index] = node;
                                        },
                                        onClick() {
                                            setInputValue(item);
                                            setOpen(false);
                                            //refs.reference.current?.focus();
                                            onListChange(item);
                                        },
                                        style: {
                                            listStyleType: 'none',
                                            padding: 0,
                                            margin: 0,
                                        },
                                    })}
                                    active={activeIndex === index}
                                >
                                    {item}
                                </Item>
                            ))}
                        </div>
                    </FloatingFocusManager>
                )}
            </FloatingPortal>
        </>
    );
};

BlobInputList.propTypes = {
    inputSize: PropTypes.oneOf(["sm", "md", "lg"] as InputSize[])
};
